package com.colin.juc.threadpool;

import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by Colin on 2020/4/4 15:11
 * email: colinzhaodong@gmail.com
 * desc: 演示每个任务执行的前后方钩子函数
 *
 * @author zhaod
 */
public class PauseableThreadPool extends ThreadPoolExecutor {
	private boolean isPaused;
	private final ReentrantLock lock = new ReentrantLock();
	private Condition unpaused = lock.newCondition();
	public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
	}

	public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
	}

	public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
	}

	public PauseableThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
	}

	@Override
	protected void beforeExecute(Thread t, Runnable r) {
		super.beforeExecute(t, r);
		lock.lock();
		try {
			while (isPaused){
				unpaused.await();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}finally {
			lock.unlock();
		}
	}

	public void pause(){
		lock.lock();
		try {
			isPaused = true;
		} finally {
			lock.unlock();
		}
	}

	public void resume(){
		lock.lock();
		try {
			isPaused = false;
			unpaused.signalAll();
		} finally {
			lock.unlock();
		}
	}

	public static void main(String[] args) throws InterruptedException {
		PauseableThreadPool pauseableThreadPool = new PauseableThreadPool(10, 20, 10L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
		Runnable runnable = new Runnable() {

			@Override
			public void run() {
				System.out.println("正在被执行");
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
		for (int i = 0; i < 10000; i++) {
			pauseableThreadPool.execute(runnable);
		}
		Thread.sleep(1500);
		pauseableThreadPool.pause();
		System.out.println("线程池被暂停了");
		Thread.sleep(1500);
		pauseableThreadPool.resume();
		System.out.println("线程池被恢复了");
	}
}
